#ifndef BSONCLIENTPOOL_INCLUDED
#define BSONCLIENTPOOL_INCLUDED

#include "mongoc.h"
#include <map>
#include <string>

using std::string;
using std::map;

class ScopedBsonClient;

class BsonClientPool
{
public:
    BsonClientPool(const string& uri);
    ~BsonClientPool();

    static void release();
private:
    BsonClientPool(const BsonClientPool& other);
    BsonClientPool& operator=(const BsonClientPool& other);

    mongoc_client_t* get();
        // returned client should be pushed/returned to pool
        // when it finished it's work

    void push( mongoc_client_t* pclient);

    friend class ScopedBsonClient;
private:
    mongoc_uri_t            *m_uri;
    mongoc_client_pool_t    *m_clientpool;
};

class ScopedBsonClient
{
public:
    ScopedBsonClient(BsonClientPool& pool):
        m_pool(pool),m_client(NULL)
    {}

    mongoc_client_t* get()
    {
        m_client = m_pool.get();
        return m_client;
    }

    void setAppName(const string& name)
    {
        if ( m_client == NULL )
            return;
        mongoc_client_set_appname(m_client,name.c_str());
    }

    ~ScopedBsonClient()
    {
        if ( m_client != NULL )
            m_pool.push(m_client);
    }

    bool insertOne( const string& db, const string& coll, bson_t* pinsert);
        // coll = collection
    string find(const string& db, const string& coll, bson_t* pquery);
        // return a json array string

    bool updateOne(const string& db, const string& coll,bson_t* pquery, bson_t* pset);
    bool deleteOne(const string& db, const string& coll,bson_t* pdel);

private:
    BsonClientPool&     m_pool;
    mongoc_client_t     *m_client;
};



#endif
